const axios = require('axios');
const path = require('path');
const webpack = require('webpack');
const MemoryFs = require('memory-fs');
const ReactDomServer = require('react-dom/server');
const proxy = require('http-proxy-middleware');
const ejs = require('ejs');
const serialize = require('serialize-javascript')
const asyncBootstrap = require('react-async-bootstrapper')
const serverConfig = require('../../build/webpack.config.server');


const getTemplate = () => {
	return new Promise((resole,reject) => {
		axios.get('http://localhost:8888/public/server.ejs')
		.then(res => {
			resole(res.data)
		})
		.catch(reject)
	})
}

const Module = module.constructor

const mfs = new MemoryFs

const serverCompiler = webpack(serverConfig);
serverCompiler.outputFileSystem = mfs;

let serverBundle,createStoreMap
serverCompiler.watch({},(err,stats) => {
	if (err) throw err
		console.log('-------'+stats);
	stats = stats.toJson();

	stats.errors.forEach(err => console.log(err))
	stats.warnings.forEach(warn => console.log(warn))
	const bundlePath = path.join(
		serverConfig.output.path,
		serverConfig.output.filename
	)
	const bundle = mfs.readFileSync(bundlePath,'utf8');
	const m = new Module()
	m._compile(bundle,'server-entry.js');
	serverBundle = m.exports.default
	createStoreMap = m.exports.createStoreMap
})

const getStoreState = (stores) => {
	return Object.keys(stores).reduce((result,storeName) => {
		result[storeName] = stores[storeName].toJson()
		return result;
	},{})
}


module.exports = function(app) {
	app.use('/public',proxy({
		target : 'http://localhost:8888'
	}))
	app.get('*',function(req,res){
		getTemplate().then(template => {
			const routerContext = {}
			const stores = createStoreMap()
			const app = serverBundle(stores,routerContext,req.url)
			asyncBootstrap(app).then( ()=> {
				if (routerContext.url) {
					res.status(302).setHeader('Location',routerContext.url)
					res.end();
					return 
				}
				const state = getStoreState(stores)
				const content = ReactDomServer.renderToString(app);
				const html = ejs.render(template,{
					appString : content,
					initialState : serialize(state)
				});
				res.send(html)
				// res.send(template.replace('<!-- app -->',content)) 
			})
		})
	})
}